package com.ln.adoms.service;

import java.text.DecimalFormat;
import java.util.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.ln.adoms.utils.QrCodeUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;

import com.ln.adoms.dao.DepartmentDao;
import com.ln.adoms.dao.GoodsDao;
import com.ln.adoms.dao.OrderDao;
import com.ln.adoms.dao.OrderLineDao;
import com.ln.adoms.dao.QrBoxCodeDao;
import com.ln.adoms.dao.QrGoodsCodeDao;
import com.ln.adoms.dao.StorageBatchDao;
import com.ln.adoms.entity.Department;
import com.ln.adoms.entity.Goods;
import com.ln.adoms.entity.Order;
import com.ln.adoms.entity.OrderLine;
import com.ln.adoms.entity.QrBoxCode;
import com.ln.adoms.entity.QrGoodsCode;
import com.ln.adoms.entity.StorageBatch;
import com.ln.adoms.entity.neum.DepartType;
import com.ln.adoms.entity.neum.FullStatus;
import com.ln.adoms.entity.neum.Status;
import com.ln.core.orm.Filtration;
import com.ln.core.orm.Filtration.MatchType;
import com.ln.core.orm.hibernate.BaseDao;
import com.ln.core.orm.hibernate.BaseService;
import com.ln.core.security.entity.Users;

@Service
@Transactional
public class GoodsService extends BaseService<Goods> {
    @Override
    @Resource(name = "goodsDao")
    public void setBaseDao(BaseDao<Goods> baseDao) {
        this.baseDao = baseDao;
    }

    @Autowired
    private DepartmentDao departmentDao;

    @Autowired
    private GoodsDao goodsDao;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private QrGoodsCodeDao qrGoodsCodeDao;
    @Autowired
    private QrBoxCodeDao qrBoxCodeDao;
    @Autowired
    private OrderLineDao orderLineDao;
    @Autowired
    private StorageBatchDao storageBatchDao;

    public List<Goods> getStockListByMidAndDid(Integer mid, Integer did) {

        return goodsDao.getStockListByMidAndDid(mid, did);
    }

    public List<Goods> getStockListByMid(Integer mid) {
        return goodsDao.getStockListByMid(mid);
    }

    public void outStock(Order order, Integer[] goodsId, HttpServletRequest request, Integer[] boxsId) throws Exception {

        if (boxsId != null) {
            dealBoxIsOpen(boxsId);
        }

        Order o = orderDao.find(order.getId());
        o.setMemo3(order.getMemo3());
        o.setOutUser(order.getOutUser());
        o.setStatus(Status.ORDER_HAS_SHIPED);
        o.setOutTime(new Date());
        for (Integer id : goodsId) {
            Goods goods = this.find(id);
            goods.setOrder(o);
            goods.setState(Status.HAS_OUT.getValue());
            this.update(goods);
        }
        Users user = (Users) request.getSession().getAttribute("USER");
        FullStatus fStatus = null;
        Department department = departmentDao.find(user.getDepartment().getId());

        if (DepartType.ZD.v().equals(department.getType().getName())) {
            fStatus = FullStatus.ZDYFH;
        } else if (DepartType.SD.v().equals(department.getType().getName())) {
            fStatus = FullStatus.SDYFH;
        } else if (DepartType.MD.v().equals(department.getType().getName())) {
            fStatus = FullStatus.MDYFH;
        }
        o.setfStatus(fStatus);
        o.addLogs(user, "出库发货"); // 记录日志
        orderDao.update(o); // 注这个位置，让上面的状态更新完了，这里才更新这个order的状态，这里的先后顺序会影响库存明细的统计
    }

    /**
     * 处理箱码是否开箱
     *
     * @param boxsId
     */
    private void dealBoxIsOpen(Integer[] boxsId) {
        for (Integer id : boxsId) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("isOpen", true);
            map.put("id", id);
            qrBoxCodeDao.batchExecute("update QrBoxCode set isOpen = :isOpen where id = :id", map);
        }
    }

    /**
     * pda 出库
     *
     * @param user
     * @param model
     * @param request
     * @param qrCode
     * @param orderLineId
     * @param orderId
     * @return
     */
    public String pdaOut(Users user, Model model, HttpServletRequest request, String qrCode, Integer[] orderLineId, Integer orderId, Integer departmentId) throws Exception {
        Order order = orderDao.find(orderId); // 取出当前操作的订单
        String msg = "";
        boolean qrFlag = false; // 二维码是否录入成功
        boolean isOrderFull = true; // 订单录入是否完成
        boolean isNumberMore = false;
        try {
            List<Goods> willOutList = new ArrayList<Goods>(); // 要出库的goods结果集
            Integer did = user.getDepartment().getId(); // 取得当前部门的ID
            qrCode = qrCode.trim().replace(" ", "");

            //2013.10.10
            String wCode = QrCodeUtil.getCode(qrCode);

            /*** 按录入的二维码查询到相应要出库的Goods ***/
            // 1. 先判断是否为箱码，先查询箱码
            String hql = "from Goods where qrCode.box.wCode = ? and department.id = ? and state = ?";
            List<Goods> goodsList = this.findList(hql, wCode, did, Status.WILL_SALE.getValue());
            if (!goodsList.isEmpty()) {
                if (goodsList.size() == goodsList.get(0).getQrCode().getBox().getGoodsNum()) {
                    willOutList.addAll(goodsList);
                } else {
                    msg = qrCode + "<span style='color:red;'>该箱已被开箱，箱码失效，请单个扫描！</span>";
                }
            } else {
                // 2. 只是单纯的货物二维码
                hql = "from Goods where qrCode.wCode = ? and department.id = ? and state = ?";
                Goods goods = this.find(hql, wCode, did, Status.WILL_SALE.getValue()); // 只是货物二维码，不是箱码的时候
                if (goods != null) {
                    willOutList.add(goods);
                }
            }

            // 查询出来要出库的goods，根据这个goods来更新相应的orderLine
            if (!willOutList.isEmpty()) {

                // 有出库的商品了，那就先查询当前这个订单中的所有orderLine
                List<OrderLine> lineList = new ArrayList<OrderLine>();
                for (Integer lineId : orderLineId) {
                    OrderLine orderLine = orderLineDao.find(lineId);
                    lineList.add(orderLine);
                }

                for (OrderLine orderLine : lineList) {
                    boolean more = true;
                    for (Goods goods : willOutList) {
                        // 二维码和订购的商品相同时才作处理
                        if (goods.getMarchandise().getId().equals(orderLine.getMarchandise().getId())) {
                            if (more && willOutList.size() > 1 && (orderLine.getItems() - orderLine.getHasIn() < willOutList.size())) {
                                msg = qrCode + "录入数量超过剩余录入数量，请单个商品录入";
                                isNumberMore = true;
                                break;
                            }
                            more = false;
                            // 只有未录入满的orderline才录入
                            if (orderLine.getHasIn() < orderLine.getItems()) {
                                // 更新goods的状态，并设置其出库所属哪个一订单order
                                goods.setOrder(order);
                                goods.setState(Status.HAS_OUT.getValue());
                                this.update(goods);
                                // 更新orderline中的计数
                                orderLine.setHasIn(orderLine.getHasIn() + 1);
                                orderLine.setHasleft(orderLine.getItems() - orderLine.getHasIn());
                                // 更新标志
                                qrFlag = true;
                            } else {
                                break;
                            }

                        }
                    }
                }

                // 出库goods处理完成后再处理orderLine,将其状态更新到数据库
                for (OrderLine orderLine : lineList) {
                    if (orderLine.getHasIn() < orderLine.getItems()) {
                        isOrderFull = false;// 订单是否完成标志
                    }
                    orderLineDao.update(orderLine);
                }
            }

            if (StringUtils.isBlank(msg)) {
                // 设置二维码状态
                if (qrFlag) {
                    msg = qrCode + "录入成功";
                    // 设置订单状态
                    if (isOrderFull) {
                        order.setMemo3("PDA订单出库");
                        order.setOutUser(user.getName());
                        order.setStatus(Status.ORDER_HAS_SHIPED);
                        FullStatus fStatus = FullStatus.ZDYFH;
                        Department department = departmentDao.find(user.getDepartment().getId());
                        if (DepartType.SD.v().equals(department.getType().getName())) {
                            fStatus = FullStatus.SDYFH;
                        } else if (DepartType.MD.v().equals(department.getType().getName())) {
                            fStatus = FullStatus.MDYFH;
                        }
                        order.setfStatus(fStatus);
                        order.setOutTime(new Date());
                        msg += "<br/>订单：" + order.getCode() + "出库完成.";


                        order.addLogs(user, "出库发货"); // 记录日志

                        orderDao.update(order);
                    }
                } else {
                    if (isNumberMore) {
                        msg = qrCode + "录入数量超过剩余录入数量，请单个商品录入";
                    } else {
                        if (qrCode.length() == 36) {
                            msg = qrCode + " <span style='color:red;'>已被使用</span>";
                        } else {
                            msg = qrCode + " <span style='color:red;'>无效</span>";
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            msg = qrCode + " <span style='color:red;'>无效</span>";
        }
        model.addAttribute("order", order); // 处理的哪个订单还是要返回到页面上去的
        model.addAttribute("msg", msg);
        if (msg.endsWith("出库完成.")) {
            List<OrderLine> orderLines = orderLineDao.findList("order.id", order.getId());
            model.addAttribute("orderLines", orderLines);
        }
        commonOut(model, departmentId);
        return msg;
    }

    /**
     * 根据 batch 和 qrCode 将货物入库，并反回相应的消息
     *
     * @param qrCode
     * @param batch
     * @return msg
     */
    public String inStore(String qrCode, Integer batchId, Model model, Integer departmentId) {
        qrCode = qrCode.trim().replace(" ", "");
        //2013.10.10
        String wCode = QrCodeUtil.getCode(qrCode);
        StorageBatch batch = storageBatchDao.find(batchId);
        int numOfStore = 0; // 入库数量
        commonPda(model, departmentId);
        model.addAttribute("inBatch", batch);
        // 先查询箱码
        QrBoxCode box = qrBoxCodeDao.find("wCode", wCode);
        if (box != null && box.getState().equals(Status.WILL_IN.getValue())) {

            // 判断规格是否正确
            if (!box.getGoodsNum().equals(batch.getMarchandise().getNumOfBox())) {
                return qrCode + " 箱码规格不正确";
            }

            // 取得本箱中未入库的二维码
            Filtration boxFilter = new Filtration(MatchType.EQ, box.getId(), "box.id");
            Filtration stateFilter = new Filtration(MatchType.EQ, Status.WILL_IN.getValue(), "state");
            List<QrGoodsCode> gList = qrGoodsCodeDao.findList(boxFilter, stateFilter);
            if (gList != null && gList.size() > 0) {
                if (gList.size() != box.getGoodsNum()) {
                    return qrCode + "该箱已被开箱，箱码失效，请单个扫描！";
                }
                if (gList.size() > (batch.getNumOfMarchandise() - batch.getNumOfMarchandiseHasDone())) {
                    return qrCode + "箱码中货物数量超过限制，请单个商品录入！";
                }
                // 新增货物 入库的时候没有设置部门ID
                for (QrGoodsCode goodQr : gList) {
                    Goods goods = new Goods();
                    goods.setDepartment(batch.getDepartment());
                    goods.setMarchandise(batch.getMarchandise());
                    goods.setProduceDate(batch.getProduceDate());
                    goods.setStorageBatch(batch);
                    goods.setQrCode(goodQr);
                    goods.setId(null);
                    goods.setState(Status.WILL_SALE.getValue());
                    this.save(goods); //
                    // 更新货物二维码表中的状态
                    goodQr.setState(Status.HAS_IN.getValue());
                    goodQr.setStorageBatch(batch);
                    qrGoodsCodeDao.update(goodQr);
                    numOfStore++;
                }
            }
            // 更新箱码的状态
            box.setState(Status.HAS_IN.getValue());
            box.setStorageBatch(batch);
            qrBoxCodeDao.update(box);
        } else {// 不是箱码
            QrGoodsCode goodQr = qrGoodsCodeDao.find("wCode", wCode);
            if (goodQr != null && goodQr.getState().equals(Status.WILL_IN.getValue())) {
                if (!goodQr.getBox().getGoodsNum().equals(batch.getMarchandise().getNumOfBox())) {
                    return qrCode + " 规格不正确";
                }
                Goods goods = new Goods();
                goods.setDepartment(batch.getDepartment());
                goods.setMarchandise(batch.getMarchandise());
                goods.setProduceDate(batch.getProduceDate());
                goods.setStorageBatch(batch);
                goods.setQrCode(goodQr);
                goods.setId(null);
                goods.setState(Status.WILL_SALE.getValue());
                this.save(goods); //
                // 更新货物二维码表中的状态
                goodQr.setState(Status.HAS_IN.getValue());
                goodQr.setStorageBatch(batch);
                qrGoodsCodeDao.update(goodQr);
                numOfStore++;
            }
        }
        if (numOfStore > 0) {
            // 更新完成的数量
            DecimalFormat df = new DecimalFormat("######0.00");
            batch.setNumOfMarchandiseHasDone(batch.getNumOfMarchandiseHasDone() + numOfStore);
            batch.setNumOfBoxHasDone(Double.valueOf(df.format(batch.getNumOfMarchandiseHasDone() / batch.getMarchandise().getNumOfBox().doubleValue())));
            // 更新批次的状态
            if (batch.getNumOfMarchandise().equals(batch.getNumOfMarchandiseHasDone())) {
                batch.setState(FullStatus.ZDYWC.v());
                storageBatchDao.update(batch);
                return qrCode + " 录入成功 <br/>入库单:" + batch.getBatchCode() + " 录入完成";
            } else {
                batch.setState(FullStatus.ZDRKZ.v());
                storageBatchDao.update(batch);
                return qrCode + " 录入成功";
            }
        } else {
            if (qrCode.length() == 36) {
                return qrCode + " <span style='color:red;'>已被使用</span>";
            } else {
                return qrCode + " <span style='color:red;'>无效</span>";
            }
        }
    }

    /**
     * 获取下拉入库单
     *
     * @param model
     * @param request
     */
    public void commonPda(Model model, Integer departmentId) {
        String hql = "from StorageBatch where department.id = ? and state != ? and state != ?";
        List<StorageBatch> batchList = storageBatchDao.findList(hql, departmentId, Status.STORAGE_BATCH_DONE.getValue(), FullStatus.ZDYWC.v());
        model.addAttribute("batchList", batchList);
    }

    /**
     * 清除当前入库批次的所有数据
     *
     * @param batchId
     * @return boolean
     */
    public void clearStoreData(Integer batchId, Model model, Integer departmentId) {
        String msg = "";
        try {
            String hql = "delete from Goods where storageBatch.id = ?";
            goodsDao.batchExecute(hql, batchId);
            String hql2 = "update QrGoodsCode set state = ? where storageBatch.id = ?";
            qrGoodsCodeDao.batchExecute(hql2, Status.WILL_IN.getValue(), batchId);
            String hql4 = "update QrBoxCode set state = ? where storageBatch.id = ?";
            qrBoxCodeDao.batchExecute(hql4, Status.WILL_IN.getValue(), batchId);
            String hql3 = "update StorageBatch set state=?,numOfBoxHasDone = 0,numOfMarchandiseHasDone = 0 where id=?";
            storageBatchDao.batchExecute(hql3, Status.STORAGE_BATCH_WILL_IN.getValue(), batchId);
            msg = "数据清除成功";
        } catch (Exception e) {
            msg = "数据清除失败";
        }
        StorageBatch batch = storageBatchDao.find(batchId);
        // 入库
        model.addAttribute("inBatch", batch);
        model.addAttribute("msg", msg);
        // 设置下拉列表
        commonPda(model, departmentId);
    }

    /**
     * 获取下拉入库单
     *
     * @param model
     * @param request
     */
    public void commonOut(Model model, Integer departmentId) {
        List<Order> orderList = orderDao.findList("from Order where ((departmentTarget.id=? and type=? ) or (department.id=? and type=?)) and status=?", departmentId, true, departmentId, false,
                Status.ORDER_WILL_SHIP);
        model.addAttribute("orderList", orderList);
    }

    /**
     * 清除当前出库批次的所有数据
     *
     * @param batchId
     * @return boolean
     */
    public void clearOutData(Integer orderId, Model model, Integer departmentId) {
        String msg = "";
        try {
            String hql = "update Goods set state=? where order.id = ?";
            goodsDao.batchExecute(hql, Status.WILL_SALE.getValue(), orderId);
            String hql2 = "update OrderLine set hasIn = 0,hasleft = 0 where order.id = ?";
            orderLineDao.batchExecute(hql2, orderId);
            msg = "数据清除成功";
        } catch (Exception e) {
            msg = "数据清除失败";
        }
        Order order = orderDao.find(orderId); // 取出当前操作的订单
        // 入库
        model.addAttribute("order", order); // 处理的哪个订单还是要返回到页面上去的
        model.addAttribute("msg", msg);
        // 设置下拉列表
        commonOut(model, departmentId);
    }

}
